use crate::solution::Solution;

impl Solution {
    pub fn generate_matrix(n: i32) -> Vec<Vec<i32>> {
        let max_num = n * n;
        let mut cur_num = 1;
        let mut matrix = vec![vec![0; n as usize]; n as usize];
        let (mut row, mut column) = (0, 0);
        let directions = vec![[0, 1], [1,0], [0, -1], [-1, 0]];
        let mut direction_index = 0;
        while cur_num <= max_num {
            matrix[row as usize][column as usize] = cur_num;
            cur_num += 1;
            let next_row = row + directions[direction_index][0];
            let next_column = column + directions[direction_index][1];
            if next_row < 0 || next_row >= n || next_column < 0 || next_column >= n || matrix[next_row as usize][next_column as usize] != 0 {
                direction_index = (direction_index + 1) % 4;
            }
            row += directions[direction_index][0];
            column += directions[direction_index][1];
        }
        matrix
    }

    pub fn generate_matrix_2(n: i32) -> Vec<Vec<i32>> {
        let mut num = 1;
        let mut matrix = vec![vec![0; n as usize]; n as usize];
        let (mut left, mut right, mut top, mut bottom) = (0, n - 1, 0, n - 1);
        while left <= right && top <= bottom {
            for column in left..=right {
                matrix[top as usize][column as usize] = num;
                num += 1;
            }
            for row in (top + 1)..=bottom {
                matrix[row as usize][right as usize] = num;
                num += 1;
            }
            if left < right && top < bottom {
                for column in ((left + 1)..right).rev() {
                    matrix[bottom as usize][column as usize] = num;
                    num += 1;
                }
                for row in ((top + 1)..=bottom).rev() {
                    matrix[row as usize][left as usize] = num;
                    num += 1;
                }
            }
            left += 1;
            right -= 1;
            top += 1;
            bottom -= 1;
        }
        matrix
    }

}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_1() {
        let n = 3;
        let res = Solution::generate_matrix(n);
        println!("{:?}", res);
        assert_eq!(res, vec![[1,2,3],[8,9,4],[7,6,5]]);
    }
}
